package fem2.gui;

import fem2.gui.pm.HofemPipelineFactory;
import fem2.gui.pm.LinePlotPipeline;
import inf.vtk.algorithms.LinePlotFilter;
import inf.vtk.pm.ActorManager;
import inf.vtk.pm.PipelineCollection;
import inf.vtk.pm.uiswing.ActorCheckBox;
import inf.vtk.pm.uiswing.LeftBox;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.lang.reflect.Field;
import java.util.LinkedList;
import java.util.List;

import javax.swing.DefaultComboBoxModel;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;

public class EdgeResultsPanel extends LeftBox implements PropertyChangeListener {

	private class OrientationEntry {

		private String name_;
		private int orientation_;

		public OrientationEntry(String name, int orientation) {
			name_ = name;
			orientation_ = orientation;
		}

		void apply() {
			getLinePlotPipeline().setOrientation(orientation_);
		}

		@Override
		public String toString() {
			return name_;
		}
	}

	private static final long serialVersionUID = 1L;

	private ActorCheckBox minMaxACB_;
	private JComboBox orientationCB_ = new JComboBox(getEntries());
	private ScalePanel scalePanel_ = new ScalePanel();
	private JCheckBox useNormalCB_ = new JCheckBox("Normal Vector");
	private ActorCheckBox visibleACB_;
	private JComboBox resultsCB_ = new JComboBox();
	private PipelineCollection pipelineCollection_;

	public EdgeResultsPanel(PipelineCollection pc) {
		pipelineCollection_ = pc;
		pipelineCollection_.addPropertyChangeListener(this);
		initialize();
	}

	private OrientationEntry[] getEntries() {
		Field[] fields = LinePlotFilter.class.getDeclaredFields();
		List<OrientationEntry> entries = new LinkedList<OrientationEntry>();

		for (int i = 0; i < fields.length; i++) {
			Field f = fields[i];
			String fname = f.getName();

			if (fname.startsWith("O_")) {
				try {
					int v = f.getInt(null);
					String label = fname.replaceFirst("O_", "");

					entries.add(new OrientationEntry(label, v));
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
		return entries.toArray(new OrientationEntry[entries.size()]);
	}

	private LinePlotPipeline getLinePlotPipeline() {
		return (LinePlotPipeline) pipelineCollection_
				.getPart(HofemPipelineFactory.PL_LINE_PLOT);
	}

	private void initAction1() {
		orientationCB_.setSelectedIndex(2);
		((OrientationEntry) orientationCB_.getSelectedItem()).apply();

		orientationCB_.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg0) {
				((OrientationEntry) orientationCB_.getSelectedItem()).apply();
				pipelineCollection_.render();
			}
		});

		NumberTextFieldListenerAdapter ntfla = new NumberTextFieldListenerAdapter() {

			@Override
			protected void apply() {
				getLinePlotPipeline().setScale(
						scalePanel_.doubleTextField_.getDoubleValue());
				getLinePlotPipeline().render();
			}

		};

		useNormalCB_.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				getLinePlotPipeline().setUseNormal(useNormalCB_.isSelected());
				getLinePlotPipeline().render();
			}
		});

		resultsCB_.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				getLinePlotPipeline().setField(
						(String) resultsCB_.getSelectedItem());
				getLinePlotPipeline().render();
			}
		});

		scalePanel_.doubleTextField_.setDoubleValue(getLinePlotPipeline()
				.getScale());
		scalePanel_.doubleTextField_.addActionListener(ntfla);
		scalePanel_.doubleTextField_.addChangeListener(ntfla);
	}

	private void initialize() {
		initLayout1();
		initAction1();
	}

	private void initLayout1() {
		ActorManager lpAM = getLinePlotPipeline().getActorManager(
				LinePlotPipeline.ACTOR_FACES);
		ActorManager lpOutlinesAM = getLinePlotPipeline().getActorManager(
				LinePlotPipeline.ACTOR_OUTLINES);
		ActorManager lpScalarBarAM = getLinePlotPipeline().getActorManager(
				LinePlotPipeline.ACTOR_SCALAR_BAR);
		ActorManager lpMML = getLinePlotPipeline().getActorManager(
				LinePlotPipeline.ACTOR_MIN_MAX_LABELS);
		ActorManager lpMMP = getLinePlotPipeline().getActorManager(
				LinePlotPipeline.ACTOR_MIN_MAX_POINTS);

		visibleACB_ = new ActorCheckBox("Visible", getLinePlotPipeline(),
				new ActorManager[] { lpAM, lpOutlinesAM, lpScalarBarAM });
		minMaxACB_ = new ActorCheckBox("Min/Max", getLinePlotPipeline(),
				new ActorManager[] { lpMML, lpMMP });

		useNormalCB_.setSelected(getLinePlotPipeline().isUseNormal());
		useNormalCB_.setToolTipText("Use orient using normal vector");

		add(new JLabel("Show:"));
		add(resultsCB_);
		add(new JLabel("Orientation:"));
		add(orientationCB_);
		add(visibleACB_);
		add(minMaxACB_);
		add(useNormalCB_);
		add(scalePanel_);
	}

	@Override
	public void propertyChange(PropertyChangeEvent evt) {
		resultsCB_.setModel(new DefaultComboBoxModel(getLinePlotPipeline()
				.getAvailableFields()));

		if (resultsCB_.getItemCount() > 0) {
			getLinePlotPipeline().setField(
					(String) resultsCB_.getSelectedItem());
		}
	}
}
